#include "icache/coordinator.h"
#include "icache/mem_cache.h"
#include "icache/disc_cache.h"

namespace icache {

void coordinator::put(cached_image_sptr const & c, last_used_position p)
{
	if (mc)
		mc->put(c, p);
	if (dc && c->id->cache_on_disc())
		dc->put(c, p);
}

cached_image_sptr coordinator::get(item_id_sptr const & id, last_used_position p)
{
	assert(id->loadable() || id->requestable());
	cached_image_sptr c;

	for (;;) {
		assert(!c);
		c = try_get(id, p);
		if (c)
			return c;

		if (id->loadable()) {
			c = cached_image::create(id);
			id->load(c->im);
			put(c, p);
			return c;
		}
		else
			id->request();
	}
}

cached_image_sptr coordinator::try_get(item_id_sptr const & id, last_used_position p)
{
	cached_image_sptr c;
	if (mc)	{
		c = mc->try_get(id, p);
		if (c) {
			if (dc && id->cache_on_disc()) {
				if (!dc->touch(id, p))
					dc->put(c, p);
			}
			return c;
		}
	}

	assert(!c);
	if (dc) {
		c = dc->try_get(id, p);
		if (c) {
			if (mc)
				mc->put(c, p);
		}
	}
	return c;
}

bool coordinator::touch(item_id_sptr const & id, last_used_position p)
{
	bool res = false;
	if (mc) {
		if (mc->touch(id, p))
			res = true;
	}
	if (dc && id->cache_on_disc()) {
		if (dc->touch(id, p))
			res = true;
	}
	return res;
}

void coordinator::remove(item_id_sptr const & id)
{
	if (mc)
		mc->remove(id);
	if (dc)
		dc->remove(id);
}

void coordinator::purge()
{
	if (mc)
		mc->purge();
	if (dc)
		dc->purge();
}

} //namespace icache
